/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sim;
/*****************************************************************************
 *                        Web3d.org Copyright (c) 2001-2005
 *                               Java Source
 *
 * This source is licensed under the BSD license.
 * Please read docs/BSD.txt for the text of the license.
 *
 * This software comes with the standard NO WARRANTY disclaimer for any
 * purpose. Use it at your own risk. If there's a problem you get to fix it.
 *
 ****************************************************************************/

// External imports
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Enumeration;
import javax.media.j3d.*;
import javax.vecmath.*;
import javax.swing.*;

import java.net.URL;
import java.net.MalformedURLException;

// Application specific imports
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
import com.sun.j3d.utils.behaviors.mouse.MouseTranslate;

import com.sun.j3d.loaders.Scene;


// Local
import java.awt.image.BufferedImage;
import java.util.Hashtable;
import org.j3d.renderer.java3d.geom.Sphere;
import org.web3d.j3d.loaders.VRML97Loader;
import vrml.*;
import vrml.node.*;
import vrml.Browser;
import vrml.field.MFString;
import vrml.field.*;
import vrml.field.SFNode;

/**
 * An example of how to use the Java3D loader interface with the Xj3D codebase.
 *
 * @author Alan Hudson
 * @version $Revision: 1.1 $
 */
public class VrmlLoader extends JFrame implements ActionListener{

    /** Flag to say if this should be a static load of files */
    private static boolean staticLoad = false;
    /** The J3D universe to hold everything */
    private SimpleUniverse universe;
    /** A canvas that can display timing information */
    private CapturingCanvas3D canvas;
    /** The whole scenegraph's root */
    private BranchGroup sceneRoot;
    /** A transform for examine navigation style */
    private TransformGroup examineGroup;

    /* A group to hold the loaded scene */
    private BranchGroup sceneGroup;

    /* A transform for the viewer position */
    private TransformGroup vpTransGroup;

    // User interface variables
    /** A label for the URL field */
    private Label urlLabel;
    private Button rbButton;
    private Scene scene = null;

    /**
     * Create a new loader
     *
     * @param initLocation The world to load
     */
    public VrmlLoader() {
        super("VRML97 Loader demo");

        Container content_pane = getContentPane();
        content_pane.setLayout(new BorderLayout());

        GraphicsConfigTemplate3D template = new GraphicsConfigTemplate3D();
        template.setDoubleBuffer(template.REQUIRED);
        GraphicsEnvironment env =
                GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice dev = env.getDefaultScreenDevice();

        GraphicsConfiguration gfxConfig = dev.getBestConfiguration(template);
        canvas = new CapturingCanvas3D(gfxConfig);

        content_pane.add("Center", canvas);

        urlLabel = new Label("File:");

        content_pane.add("North", urlLabel);

        rbButton = new Button("Refresh");
        rbButton.setActionCommand("refresh");
        rbButton.addActionListener(this);
        content_pane.add("South", rbButton);

        universe = new SimpleUniverse(canvas);
        universe.setJ3DThreadPriority(Thread.NORM_PRIORITY);

        ViewingPlatform viewingPlatform = universe.getViewingPlatform();
        vpTransGroup = viewingPlatform.getViewPlatformTransform();
        Viewer viewer = universe.getViewer();

        View view = viewer.getView();

        // TODO: Decide a real value for this.  Can't be infinite because
        // front/back ratio decides z precision
        view.setBackClipDistance(100);
        setupNavigation();

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //setSize(800, 600);
        setSize(1024, 768);
        setLocation(0, 0);
        setVisible(true);


    }

    //----------------------------------------------------------
    // Methods local to loader
    //----------------------------------------------------------
    /**
     * Setup the navigation system.  We use a simple examine behavior
     */
    private void setupNavigation() {

        sceneRoot = new BranchGroup();
        sceneRoot.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);

        examineGroup = new TransformGroup();
        examineGroup.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
        examineGroup.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
        examineGroup.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
        examineGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        examineGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        examineGroup.setCapability(TransformGroup.ALLOW_LOCAL_TO_VWORLD_READ);
        sceneRoot.addChild(examineGroup);

        BoundingSphere behaviorBounds = new BoundingSphere(new Point3d(),
                Double.MAX_VALUE);


        Background background = createBackground();
        if (background != null)
        sceneRoot.addChild(background);

        MouseRotate mr = new MouseRotate();
        mr.setTransformGroup(examineGroup);
        mr.setSchedulingBounds(behaviorBounds);
        sceneRoot.addChild(mr);

        MouseTranslate mt = new MouseTranslate();
        mt.setTransformGroup(examineGroup);
        mt.setSchedulingBounds(behaviorBounds);
        sceneRoot.addChild(mt);

        MouseZoom mz = new MouseZoom();
        mz.setTransformGroup(examineGroup);
        mz.setSchedulingBounds(behaviorBounds);
        sceneRoot.addChild(mz);

        universe.addBranchGraph(sceneRoot);

    }

    /**
     * Load the given file into the scene.
     *
     * @param filename The name of the file or the URL to load
     */
    private void loadFile(String file) {

        int flag = VRML97Loader.LOAD_ALL;

        if (staticLoad) {
            flag &= ~VRML97Loader.LOAD_BEHAVIOR_NODES;
        }

        VRML97Loader loader = new VRML97Loader(flag);

        // if the file is a directory, ignore it
        File f = new File(file);
        if (f.exists() && !f.isFile()) {
            System.out.println("Can't load directories specified");
            System.exit(1);
        }

        URL url = null;
        //Scene scene = null;

        try {
            url = new URL(file);
        } catch (MalformedURLException badUrl) {
            // if the location is not a URL, this is what you get
        }

        try {
            if (url != null) {
                scene = loader.load(url);
            } else {
                scene = loader.load(file);
            }
            
        } catch (Exception e) {
            System.out.println("Exception loading URL:" + e);
            e.printStackTrace();
            System.exit(0);
        }

        urlLabel.setText("File " + file);

        //Tested by RB
        int int_number_of_be = scene.getBehaviorNodes().length;
        vrml.BaseNode a = new BaseNode() {};
        Browser browser = a.getBrowser();
        //Viewscene.getViewGroups();
        //Browser browser = this.get
        //browser.createVrmlFromString("tiep.wrl");
        System.out.println("I am RB");
       // System.out.println(browser.getName());
        Behavior[] be = scene.getBehaviorNodes();
        //System.out.println(be[1].getName());
        Hashtable defTable = scene.getNamedObjects();
        TransformGroup seat = (TransformGroup) defTable.get("Shape");
        //System.out.println(seat.getAllChildren().nextElement().toString());

        //End testing

        if (scene != null) {
            // get the scene group
            sceneGroup = scene.getSceneGroup();
            sceneGroup.setCapability(BranchGroup.ALLOW_DETACH);
            sceneGroup.setCapability(BranchGroup.ALLOW_BOUNDS_READ);
            sceneGroup.compile();

            // add the scene group  to the scene
            examineGroup.addChild(sceneGroup);

            // now that the scene group is "live" we can inquire the bounds
            setViewpoint();
            setupLighting(scene);

            System.out.println(scene.getBehaviorNodes().length);
            Behavior[] behavior = scene.getBehaviorNodes();
            System.out.println("There is: ");
            for(int i = 0; i < behavior.length; i++){
                System.out.println(behavior[i].getNumSchedulingIntervals());
                //System.out.println(behavior[i].get);
            }
            
        }
    }

    /**
     * Setup the scene's view
     */
    private void setViewpoint() {
        Transform3D viewTrans = new Transform3D();
        Transform3D eyeTrans = new Transform3D();

        // put the View at the standard VRML default position 0,0,10
        //Vector3f pos = new Vector3f(0, 0, 10);
        Vector3f pos = new Vector3f(0, 0, 30);
        eyeTrans.set(pos);
        viewTrans.mul(eyeTrans);

        // set the view transform
        vpTransGroup.setTransform(viewTrans);
    }

    /**
     * Setup the worlds lighting.  If none is provided in the VRML file then
     * we create a simple headlight
     *
     * @param scene The scene to source the lights from
     */
    private void setupLighting(Scene scene) {
        Light lights[] = scene.getLightNodes();

        if (lights == null) {
            BranchGroup lightBG = new BranchGroup();
            BoundingSphere lightBounds =
                    new BoundingSphere(new Point3d(), Double.MAX_VALUE);
            DirectionalLight headLight =
                    new DirectionalLight(new Color3f(0.0f, 0.0f, 0.0f),
                    new Vector3f(0, 0, -1));
            headLight.setCapability(Light.ALLOW_STATE_WRITE);
            headLight.setInfluencingBounds(lightBounds);
            lightBG.addChild(headLight);
            sceneRoot.addChild(lightBG);
            //sceneRoot.removeChild(lightBG);
        }
    }

    protected Background createBackground() {
    Background back = new Background(new Color3f(0.9f, 0.9f, 0.9f));
    back.setApplicationBounds(createApplicationBounds());
    return back;
  }
    protected Bounds createApplicationBounds() {
        return new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
    }

    //Added by Quest
    public void actionPerformed(ActionEvent e){
        String strRefresh = e.getActionCommand();
        if("refresh".equals(strRefresh)){
            setupLighting(scene);
            addNode();
            //loadFile("ball16.wrl");
            JOptionPane.showMessageDialog(this, "You haven't written codes for this button");
        }
    }

    private void addNode(){
        BranchGroup objRoot = new BranchGroup();
        Sphere sphere = new Sphere(0.25f);
        TransformGroup objTrans = new TransformGroup();
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        Transform3D pos = new Transform3D();
        pos.setTranslation(new Vector3f(0.0f, 0.0f, 0.0f));
        objTrans.setTransform(pos);
        objTrans.addChild(sphere);
        objRoot.addChild(objTrans);
        sceneRoot.addChild(objRoot);

    }
    private static int postSwapCount_ = 0;

    public void capturePicture(){
         // Now strip out the image info
        canvas.x = 0;
        canvas.y = 0;
        canvas.width = 1024;
        canvas.height = 768;
        canvas.fillBuffer(true);
	    BufferedImage img = canvas.getFrameAsImage();

	    // write that to disk....
	    try {
            FileOutputStream out = new FileOutputStream("Capture"+ postSwapCount_+".jpg");
            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
            JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(img);
            param.setQuality(0.9f,false); // 90% qualith JPEG
            encoder.setJPEGEncodeParam(param);
            encoder.encode(img);
            out.close();
	    } catch ( IOException e ) {
            System.out.println("I/O exception!");
	    }
	    postSwapCount_++;

    }


    /**
     * A main body for running as an application
     *
     * @param args The arugment array
     */
    public static void main(String[] args) throws InterruptedException {

//        String locString = null;
//
//        if (args.length == 0) {
//            System.out.println("No file to display");
//            System.out.println("Usage: java Java3DLoaderDemo [-static] pathname | URL");
//            System.exit(0);
//        }
//
//        staticLoad = args[0].equals("-static");
//
//        if(((args.length == 1) && staticLoad) ||
//           ((args.length == 2) && !staticLoad)) {
//
//            System.out.println("No file to display");
//            System.out.println("Usage: java Java3DLoaderDemo [-static] pathname | URL");
//            System.exit(0);
//        }
//
//        String filename = (args.length == 1) ? args[0] : args[1];

        String filename = "vrml/people.wrl";
        VrmlLoader demo = new VrmlLoader();
        demo.loadFile(filename);

        while(true){
            Thread.sleep(3);
            demo.capturePicture();
        }

    }
}

